<?php


namespace GordenSong\Laravel\Templates;


use GordenSong\Laravel\Exceptions\BladeFileNotFoundException;
use GordenSong\Laravel\Exceptions\FilePutContentException;
use GordenSong\Laravel\Exceptions\TargetFileExistsException;
use Illuminate\Filesystem\Filesystem;
use Illuminate\View\Factory;

abstract class AbstractTemplate
{
	/**
	 * @param false $force 强制输出
	 * @throws TargetFileExistsException
	 * @throws BladeFileNotFoundException
	 * @throws FilePutContentException
	 */
	public function output(bool $force = false)
	{
		$this->files()->ensureDirectoryExists(dirname($this->targetFile()));

		if (!$this->files()->exists($bladeFile = $this->bladeFile())) {
			throw new BladeFileNotFoundException($bladeFile);
		}
		if ($this->files()->exists($this->targetFile()) && !$force) {
			throw new TargetFileExistsException($this->targetFile());
		}
		$written = $this->files()->put($this->targetFile(), $this->compile());
		if ($written === false) {
			throw new FilePutContentException($this->targetFile());
		}
	}

	/**
	 * @return Filesystem
	 */
	protected function files(): Filesystem
	{
		return app(Filesystem::class);
	}

	/**
	 * @return Factory
	 */
	protected function view(): Factory
	{
		return app(Factory::class);
	}

	/**
	 * @return string
	 */
	public function compile(): string
	{
		$output = '<?php' . "\n\n";
		$output .= $this->view()
			->file($this->bladeFile(), $this->getCompiledData())
			->render();

		return $output;
	}

	public abstract function targetFile(): string;

	public abstract function bladeFile(): string;

	public abstract function getCompiledData(): array;

}